Powershell scripts/Get Security Assessments (Recommendations)/Get-SecAssessment.ps1 (88 lines of code) (raw):

<# .SYNOPSIS Will query resources for their own Security assessments .DESCRIPTION Will query security assessments on certain resource types .PARAMETER AssessmentId Guid for a security assessment can be found in Microsft Defender for Azure .PARAMETER ResourceId A single resource ID to query the Security Assessment against .PARAMETER ResourceType A resource type to query the Security Assessment against (ie.: Microsoft.Compute/virtualMachines) .PARAMETER SubscriptionId Subscription ID(s) where the resources are located .PARAMETER Status Statuses to query for (ie.: Healthy, Unhealthy) .PARAMETER ApiVersion Apiversion that you want to query against .PARAMETER SubAssessment Returns subassessments if available .EXAMPLE Get-SecAssessment -AssessmentId 'd1db3318-01ff-16de-29eb-28b344515626' -ResourceType 'Microsoft.Compute/virtualMachines' #> function Get-SecAssessment { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [System.Guid]$AssessmentId, [Parameter(Mandatory, ParameterSetName = 'ResourceId')] [ValidateNotNullOrEmpty()] [System.String]$ResourceId, [Parameter(Mandatory, ParameterSetName = 'ResourceType')] [ValidateNotNullOrEmpty()] [System.String]$ResourceType, [Parameter()] [ValidateNotNullOrEmpty()] [System.Guid[]] $SubscriptionId, [Parameter()] [ValidateNotNullOrEmpty()] [System.String[]] $Status = @('Unhealthy'), [Parameter()] [ValidateNotNullOrEmpty()] [System.String]$ApiVersion = 'api-version=2020-01-01', [Parameter()] [switch] $SubAssessment ) begin { $azGraphArgs = @{} if ($SubscriptionId) { $azGraphArgs.Subscription = $SubscriptionId.Guid } if ($PSCmdlet.ParameterSetName -eq 'ResourceId') { $resources = Search-AzGraph -Query "resources | where id =~ '$ResourceId'" @azGraphArgs } else { $resources = Search-AzGraph -Query "resources | where type =~ '$ResourceType'" @azGraphArgs } $output = [System.Collections.Generic.List[pscustomobject]]::new() } process { $token = (Get-AzAccessToken -ErrorAction Stop).Token $invokeRestMethodArgs = @{ Header = @{'Authorization' = "Bearer $token" } Method = 'GET' } $resources.ForEach{ $resource = $_ $invokeRestMethodArgs.Uri = 'https://management.azure.com{0}/providers/Microsoft.Security/assessments/{1}?{2}' -f $resource.id, $AssessmentId, $ApiVersion try { $assessment = (Invoke-RestMethod @invokeRestMethodArgs) } catch { if (-not ($_.ErrorDetails.Message | ConvertFrom-Json).Error.Code -eq 'AssessmentNotFound') { throw $_ } } if ($assessment.properties.additionalData.subAssessmentsLink -and $SubAssessment) { $subAssessments = Get-SecSubAssessment -SubAssessmentLink $assessment.properties.additionalData.subAssessmentsLink } if ($subAssessments) { $subAssessments.Where{ $_.properties.status.code -in $Status }.ForEach{ $null = $output.Add($_) } } elseif ($assessment) { $assessment.Where{ $_.properties.status.code -in $Status }.ForEach{ $null = $output.Add($_) } } } } end { $output } }